#include <Python.h>
#include "structmember.h"
//#include "canCore.h"

typedef struct {
    PyObject_HEAD
    PyObject *source;
} pyCan;

static void pyCan_dealloc(pyCan* self) {
    Py_XDECREF(self->source);
    self->ob_type->tp_free((PyObject*)self);
}

static PyObject * pyCan_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
	pyCan *self;

    self = (pyCan *)type->tp_alloc(type, 0);
    if(self != NULL)
    {
        self->source = PyString_FromString("");
        if(self->source == NULL) {
            Py_DECREF(self);
            return NULL;
        }
    }

    return (PyObject *)self;
}

static int
pyCan_init(pyCan *self, PyObject *args, PyObject *kwds)
{
    PyObject *source=NULL, *tmp;

    static char *kwlist[] = {"source", NULL};

    if (! PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist,
                                      &source))
        return -1;

    if (source) {
        tmp = self->source;
        Py_INCREF(source);
        self->source = source;
        Py_XDECREF(tmp);
    }

    return 0;
}

static PyMemberDef pyCan_members[] = {
    {"source", T_OBJECT_EX, offsetof(pyCan, source), 0,
     "Input source"},
    {NULL}  /* Sentinel */
};

static PyObject * pyCan_read(pyCan* self)
{
    //pyCanCore dummy;
    //char* dummyString = dummy.fakeReading();

    char* dummyString = "Hello world";

	PyObject *result;
    result = Py_BuildValue("s", dummyString);
    return result;
};

static PyMethodDef pyCan_methods[] = {
    {"read", (PyCFunction)pyCan_read, METH_NOARGS,
     "Reads from the pyCan channel"
    },
    {NULL}  /* Sentinel */
};

static PyTypeObject pyCanType = {
    PyObject_HEAD_INIT(NULL)
    0,
    "pyCan.pyCan",
    sizeof(pyCan),
    0,
    (destructor)pyCan_dealloc,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
    "pyCan objects",
    0,
    0,
    0,
    0,
    0,
    0,
    pyCan_methods,
    pyCan_members,
    0,
    0,
    0,
    0,
    0,
    0,
    (initproc)pyCan_init,
    0,
    pyCan_new,
};

PyObject* version(PyObject* self)
{
    return Py_BuildValue("s", "pyCan module version 1.0");
}

static PyMethodDef functions[] = {
    {"version", (PyCFunction)version, METH_NOARGS},
    {NULL, NULL, 0, NULL} /* Sentinel */
};

extern "C"
PyMODINIT_FUNC initpyCan(void)
{
    PyObject* m;

    if (PyType_Ready(&pyCanType) < 0)
        return;

    m = Py_InitModule3("pyCan", functions, "pyCan module");

    if (m == NULL)
        return;

    Py_INCREF(&pyCanType);
    PyModule_AddObject(m, "pyCan", (PyObject *)&pyCanType);
}
